/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License");  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * http//www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is ART OWL API.
 *
 * The Initial Developer of the Original Code is University of Roma Tor Vergata.
 * Portions created by University of Roma Tor Vergata are Copyright (C) 2009.
 * All Rights Reserved.
 *
 * The ART OWL API were developed by the Artificial Intelligence Research Group
 * (art.uniroma2.it) at the University of Roma Tor Vergata
 * Current information about the ART OWL API can be obtained at 
 * http://art.uniroma2.it/owlart
 *
 */

package it.uniroma2.art.owlart.io;

import it.uniroma2.art.owlart.exceptions.ModelAccessException;
import it.uniroma2.art.owlart.model.ARTBNode;
import it.uniroma2.art.owlart.model.ARTLiteral;
import it.uniroma2.art.owlart.model.ARTNode;
import it.uniroma2.art.owlart.model.ARTNodeFactory;
import it.uniroma2.art.owlart.model.ARTResource;
import it.uniroma2.art.owlart.model.ARTURIResource;
import it.uniroma2.art.owlart.model.impl.ARTNodeFactoryImpl;
import it.uniroma2.art.owlart.models.PrefixMapping;

/**
 * This class provides static methods for serializing/deserializing RDF nodes to/from the NT format. Specific
 * methods for URI, BNodes and Literals are provided, as well as transformations for Resources and Nodes in
 * general.
 * 
 * @author Armando Stellato
 * 
 */
public class RDFNodeSerializer {

	static ARTNodeFactory nodeFact = new ARTNodeFactoryImpl();

	/**
	 * NTRIPLES format for the serialization of nodes. Depends on the nature of the node.
	 * 
	 * @param node
	 * @return for URIs/IRIs: &lt;URI/IRI&gt;, for BNodes: the _:<code>id</code> notation, for literals:
	 *         literalvalue[^^&lt;datatype&gt;|@languagetag]
	 */
	public static String toNT(ARTURIResource node) {
		return "<" + node.asURIResource().getURI() + ">";
	}

	/**
	 * NTRIPLES format for the serialization of nodes. Depends on the nature of the node.
	 * 
	 * @param node
	 * @return for URIs/IRIs: &lt;URI/IRI&gt;, for BNodes: the _:<code>id</code> notation, for literals:
	 *         "literalvalue"[^^&lt;datatype&gt;|@languagetag]
	 */
	public static String toNT(ARTBNode node) {
		return "_:" + node.asBNode().getID();
	}

	/**
	 * NTRIPLES format for the serialization of nodes. Depends on the nature of the node.
	 * 
	 * @param node
	 * @return for URIs/IRIs: &lt;URI/IRI&gt;, for BNodes: the _:<code>id</code> notation, for literals:
	 *         "literalvalue"[^^&lt;datatype&gt;|@languagetag]
	 */
	public static String toNT(ARTLiteral node) {
		return node.asLiteral().toString();
	}

	/**
	 * NTRIPLES format for the serialization of nodes. Depends on the nature of the node.
	 * 
	 * @param node
	 * @return for URIs/IRIs: &lt;URI/IRI&gt;, for BNodes: the _:<code>id</code> notation, for literals:
	 *         "literalvalue"[^^&lt;datatype&gt;|@languagetag]
	 */
	public static String toNT(ARTResource node) {
		if (node.isURIResource())
			return "<" + node.asURIResource().getURI() + ">";
		// it's blank
		return "_:" + node.asBNode().getID();
	}

	/**
	 * NTRIPLES format for the serialization of nodes. Depends on the nature of the node.
	 * 
	 * @param node
	 * @return for URIs/IRIs: &lt;URI/IRI&gt;, for BNodes: the _:<code>id</code> notation, for literals:
	 *         "literalvalue"[^^&lt;datatype&gt;|@languagetag]
	 */
	public static String toNT(ARTNode node) {
		if (node.isURIResource())
			return "<" + node.asURIResource().getURI() + ">";
		if (node.isBlank())
			return "_:" + node.asBNode().getID();

		return node.asLiteral().toString();
	}

	public static ARTLiteral createLiteral(String literal, PrefixMapping map) throws ModelAccessException {
		String partiallyPrunedLiteral = literal.substring(1);
		if (partiallyPrunedLiteral.contains("\"^^")) {
			// System.err.println("creating datatype literal");
			String[] literalPieces = partiallyPrunedLiteral.split("\"\\^\\^");
			String datatypeURI;
			if (literalPieces[1].startsWith("<"))
				datatypeURI = literalPieces[1].substring(1, literalPieces[1].length() - 1);
			else
				datatypeURI = map.expandQName(literalPieces[1].substring(0, literalPieces[1].length()));
			return nodeFact.createLiteral(literalPieces[0], nodeFact.createURIResource(datatypeURI));
		}

		if (partiallyPrunedLiteral.contains("\"@")) {
			// System.err.println("creating lang literal");
			int lastIndexOfAt = partiallyPrunedLiteral.lastIndexOf("\"@");
			return nodeFact.createLiteral(partiallyPrunedLiteral.substring(0, lastIndexOfAt),
					partiallyPrunedLiteral.substring(lastIndexOfAt + 2));
		}

		System.err.println("creating simple literal");
		return nodeFact
				.createLiteral(partiallyPrunedLiteral.substring(0, partiallyPrunedLiteral.length() - 1));
	}

	public static ARTURIResource createURI(PrefixMapping map, String QNameOrURI) throws ModelAccessException {
		String trueURI;
		if (QNameOrURI.startsWith("<")) {
			trueURI = QNameOrURI.substring(1, QNameOrURI.length() - 1);
		} else {
			trueURI = map.expandQName(QNameOrURI);
		}
		return nodeFact.createURIResource(trueURI);
	}

	public static ARTBNode createBNode(String bnode) throws ModelAccessException {
		String bNodeId = bnode.substring(2);
		return nodeFact.createBNode(bNodeId);
	}

	public static ARTResource createResource(PrefixMapping map, String resource) throws ModelAccessException {
		if (isBlank(resource))
			return createBNode(resource);
		return createURI(map, resource);
	}

	public static ARTNode createNode(PrefixMapping map, String node) throws ModelAccessException {
		if (isLiteral(node))
			return createLiteral(node, map);
		return createResource(map, node);
	}

	public static boolean isName(String nodeName) {
		if (nodeName.startsWith("<"))
			return true;
		if (!isLiteral(nodeName) && nodeName.contains(":"))
			return true;
		return false;
	}

	public static boolean isBlank(String serNode) {
		if (serNode.startsWith("_:"))
			return true;
		return false;
	}

	public static boolean isResource(String serNode) {
		if (isBlank(serNode))
			return true;
		if (isName(serNode))
			return true;
		return false;
	}

	public static boolean isLiteral(String serNode) {
		if (serNode.startsWith("\""))
			return true;
		return false;
	}
}
